package com.entmanage.base.oa.service.impl;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import com.entmanage.base.oa.domain.OaLeaveApply;
import com.entmanage.common.core.domain.entity.SysUser;
import com.entmanage.common.utils.StringUtils;
import com.entmanage.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.entmanage.common.utils.SecurityUtils;
import com.entmanage.base.oa.mapper.OaOvertimeApplyMapper;
import com.entmanage.base.oa.domain.OaOvertimeApply;
import com.entmanage.base.oa.service.IOaOvertimeApplyService;

/**
 * 加班申请Service业务层处理
 *
 * @author lsq
 * @date 2025-09-26
 */
@Service
public class OaOvertimeApplyServiceImpl implements IOaOvertimeApplyService
{
    @Autowired
    private OaOvertimeApplyMapper oaOvertimeApplyMapper;

    @Autowired
    private JavaMailSender javaMailSender;

    @Autowired
    private ISysUserService sysUserService;

    private static final Logger log = LoggerFactory.getLogger(OaLeaveApplyServiceImpl.class);

    /**
     * 查询加班申请
     *
     * @param id 加班申请主键
     * @return 加班申请
     */
    @Override
    public OaOvertimeApply selectOaOvertimeApplyById(Long id)
    {
        return oaOvertimeApplyMapper.selectOaOvertimeApplyById(id);
    }

    /**
     * 查询加班申请列表
     *
     * @param oaOvertimeApply 加班申请
     * @return 加班申请
     */
    @Override
    public List<OaOvertimeApply> selectOaOvertimeApplyList(OaOvertimeApply oaOvertimeApply)
    {
        return oaOvertimeApplyMapper.selectOaOvertimeApplyList(oaOvertimeApply);
    }

    /**
     * 新增加班申请
     *
     * @param oaOvertimeApply 加班申请
     * @return 结果
     */
    @Override
    public int insertOaOvertimeApply(OaOvertimeApply oaOvertimeApply)
    {
        // 保存用户和部门ID
        oaOvertimeApply.setUserId(SecurityUtils.getUserId());
        oaOvertimeApply.setDeptId(SecurityUtils.getDeptId());
    oaOvertimeApply.setCreateBy(SecurityUtils.getUsername());
        return oaOvertimeApplyMapper.insertOaOvertimeApply(oaOvertimeApply);
    }

    /**
     * 修改加班申请
     *
     * @param oaOvertimeApply 加班申请
     * @return 结果
     */
    @Override
    public int updateOaOvertimeApply(OaOvertimeApply oaOvertimeApply)
    {
    oaOvertimeApply.setUpdateBy(SecurityUtils.getUsername());
        return oaOvertimeApplyMapper.updateOaOvertimeApply(oaOvertimeApply);
    }

    /**
     * 批量删除加班申请
     *
     * @param ids 需要删除的加班申请主键
     * @return 结果
     */
    @Override
    public int deleteOaOvertimeApplyByIds(Long[] ids)
    {
        return oaOvertimeApplyMapper.deleteOaOvertimeApplyByIds(ids);
    }

    /**
     * 删除加班申请信息
     *
     * @param id 加班申请主键
     * @return 结果
     */
    @Override
    public int deleteOaOvertimeApplyById(Long id)
    {
        return oaOvertimeApplyMapper.deleteOaOvertimeApplyById(id);
    }

    @Override
    @Async
    public void sendOvertimeApprovalEmail(
            List<Long> approverIds,
            List<Long> ccIds,
            String startTime,
            String endTime,
            String reason,
            String duration,
            String applicantName) {

        log.info("【开始发送加班审批邮件】时长={}小时，审核人IDs={}, 抄送IDs={}",
                duration,
                approverIds != null ? approverIds : "无",
                ccIds != null ? ccIds : "无");

        // 参数基本校验
        if (StringUtils.isEmpty(reason)) {
            log.warn("邮件发送中止：加班理由为空");
            return;
        }
        if (StringUtils.isEmpty(startTime) || StringUtils.isEmpty(endTime)) {
            log.warn("邮件发送中止：时间范围缺失");
            return;
        }

        Set<String> toEmails = new HashSet<>();
        Set<String> ccEmails = new HashSet<>();

        // 使用 SysUserService 从 sys_user 表查询邮箱
        if (approverIds != null && !approverIds.isEmpty()) {
            List<SysUser> approvers = sysUserService.selectUserByIds(approverIds);
            toEmails.addAll(filterValidEmails(approvers, "审核人"));
        }

        if (ccIds != null && !ccIds.isEmpty()) {
            List<SysUser> ccs = sysUserService.selectUserByIds(ccIds);
            ccEmails.addAll(filterValidEmails(ccs, "抄送人"));
        }

        if (toEmails.isEmpty() && ccEmails.isEmpty()) {
            log.warn("未找到任何有效邮箱地址，终止发送");
            return;
        }

        // 构建邮件内容
        String subject = "[加班申请] " + applicantName + " 申请加班 - " + duration + "小时";
        String content = String.format(
                "您好：\n\n" +
                        "%s 提交了一条加班申请，加班时间为：%s 至 %s，预计加班时长：%s 小时。\n\n" +
                        "加班事由：%s\n\n" +
                        "请登录OA系统进行查看或审批。\n\n" +
                        "—— OA系统自动通知",
                applicantName != null ? applicantName : "某员工",
                startTime,
                endTime,
                duration,
                StringUtils.isEmpty(reason) ? "无" : reason
        );

        try {
            SimpleMailMessage message = new SimpleMailMessage();
            message.setFrom("1911708828@qq.com");
            message.setSubject(subject);
            message.setText(content);

            // 发送给审批人
            if (!toEmails.isEmpty()) {
                message.setTo(toEmails.toArray(new String[0]));
                javaMailSender.send(message);
                toEmails.forEach(email -> log.info("加班审批邮件已发送至审核人: {}", email));
            }

            // 抄送给抄送人（单独发送，避免 To/Cc 混合问题）
            if (!ccEmails.isEmpty()) {
                SimpleMailMessage ccMessage = new SimpleMailMessage(message);
                ccMessage.setTo(ccEmails.toArray(new String[0]));
                javaMailSender.send(ccMessage);
                ccEmails.forEach(email -> log.info("加班审批邮件已抄送至: {}", email));
            }

            log.info("【加班审批邮件发送完成】共发送 {} 封邮件", toEmails.size() + ccEmails.size());

        } catch (Exception e) {
            log.error("发送加班审批邮件时发生异常", e);
        }
    }

    /**
     * 从 SysUser 列表中提取非空邮箱
     */
    private Set<String> filterValidEmails(List<SysUser> users, String role) {
        return users.stream()
                .filter(user -> user != null && StringUtils.isNotEmpty(user.getEmail()))
                .map(SysUser::getEmail)
                .collect(Collectors.toSet());
    }

    @Override
    public List<OaOvertimeApply> selectByApproverId(Long approverId) {
        return oaOvertimeApplyMapper.selectByApproverId(approverId);
    }

    @Override
    public List<OaOvertimeApply> selectByCcId(Long currentUserId) {
        return oaOvertimeApplyMapper.selectByCcId(currentUserId);
    }

}
